/*
 * Copyright (C) 2008 Alessandro Sivieri <alessandro.sivieri@chimera-bellerofonte.eu>.
 *
 *  This file is part of Daex.
 *
 *  Daex is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Foobar is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 */
package eu.chimera_bellerofonte.tesi.ui.models;

import java.beans.IndexedPropertyChangeEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;

import javax.swing.table.DefaultTableModel;

import eu.chimera_bellerofonte.tesi.DaexLogger;
import eu.chimera_bellerofonte.tesi.encoding.EncodingOps;


/**
 * <p>Modello di gestione della tabella di progresso del
 * processo di encoding.</p>
 * <p>Questo modello di tabella puo' essere costruito con
 * l'immediata lista di stringhe da visualizzare nella colonna
 * "Titolo", e le altre colonne vengono automaticamente
 * costruite con valori di riferimento relativi all'avanzamento
 * (il numero di traccia corrisponde ad un identificativo
 * relativo alla sola tabella dei processi, l'operazione e'
 * di attesa); tale lista puo' anche essere comunicata in un
 * secondo momento (il refresh in questo caso e' automatico).
 * <br>
 * Qualunque metodo di questa classe assicura l'aggiornamento
 * della visualizzazione della tabella; questo modello non
 * lavora su una base di dati agganciata alla base di dati generale
 * dell'applicativo, quindi le modifiche devono essere fatte
 * di volta in volta (su questa logica e' costruito l'esecutore),
 * utilizzando i metodi per settare i nuovi valori delle operazioni
 * o per svuotare la lista e caricarne eventualmente una nuova.</p>
 * <p>La classe puo' inoltre rimanere in ascolto di eventi che le
 * indichino eventuali modifiche nella visualizzazione delle righe;
 * gli eventi di questo tipo devono necessariamente essere indicizzati,
 * in caso contrario vengono ignorati.</p>
 * 
 * @see eu.chimera_bellerofonte.tesi.encoding.DefaultEncoderExecutor
 * @author Sivieri Alessandro
 * @author Vitucci Nicola
 * @version 11/mag/07
 */
public class DaexProgressTableModel extends DefaultTableModel implements PropertyChangeListener
{
	static final long serialVersionUID = 1L;

	/**
	 * Elenco delle colonne pubblicate.
	 */
	public static final String[] COLUMNS={"Traccia n.", "Titolo", "Operazione"};
	
	private ArrayList<ElementStruct> list=null;

	/**
	 * 
	 * Costruttore; inizializza la lista interna come vuota,
	 * non visualizzando alcuna riga.
	 */
	public DaexProgressTableModel()
	{
		list=new ArrayList<ElementStruct>(0);
	}
	
	/**
	 * 
	 * Costruttore; setta la lista con le righe indicate.
	 * 
	 * @param titles i titoli da visualizzare
	 */
	public DaexProgressTableModel(String[] titles)
	{
		list=new ArrayList<ElementStruct>(0);
		for(int i=1; i<=titles.length; i++)
		{
			list.add(new ElementStruct(i, titles[i-1], EncodingOps.OPWAIT));
		}
	}
	
	/**
	 * @see javax.swing.table.DefaultTableModel#getColumnCount()
	 */
	@Override
	public int getColumnCount()
	{
		return COLUMNS.length;
	}

	/**
	 * @see javax.swing.table.DefaultTableModel#getColumnName(int)
	 */
	@Override
	public String getColumnName(int arg0)
	{
		return COLUMNS[arg0];
	}

	/**
	 * @see javax.swing.table.DefaultTableModel#getRowCount()
	 */
	@Override
	public int getRowCount()
	{
		return ( list != null ) ? list.size() : 0;
	}

	/**
	 * @see javax.swing.table.DefaultTableModel#getValueAt(int, int)
	 */
	@Override
	public Object getValueAt(int arg0, int arg1)
	{
		Object o=null;
		
		switch(arg1)
		{
			case 0:
				o=list.get(arg0).number;
				break;
			case 1:
				o=list.get(arg0).title;
				break;
			case 2:
				o=list.get(arg0).op.getName();
				break;
			default:
				DaexLogger.getDaexLogger().severe("Tentativo di accesso a colonna sconosciuta in TableProgress: "+arg1);
				break;
		}
		return o;
	}

	/**
	 * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
	 */
	@Override
	public Class<?> getColumnClass(int arg0)
	{
		return getValueAt(0, arg0).getClass();
	}
	
	/**
	 * Metodo per settare una nuova voce di operazione al
	 * sistema.
	 * 
	 * @param i l'indice della riga da settare
	 * @param op la nuova operazione corrente alla traccia
	 */
	public void setNewOp(int i, EncodingOps op)
	{
		list.get(i).op=op;
		fireTableCellUpdated(i, 2);
	}
	
	/**
	 * Metodo per svuotare il modello.
	 */
	public void clear()
	{
		if(getRowCount()>0)
		{
			for(int i=0; i<getRowCount(); i++)
			{
				removeRow(i);
			}
			fireTableDataChanged();
		}
	}
	
	/**
	 * Metodo per settare le nuove righe alla lista.
	 * 
	 * @param titles le rige da agganciare
	 */
	public void setList(String[] titles)
	{
		list.clear();
		for(int i=1; i<=titles.length; i++)
		{
			list.add(new ElementStruct(i, titles[i-1], EncodingOps.OPWAIT));
		}
		fireTableDataChanged();
	}
	
	/**
	 * Classe di tipo "struct" per utilita' nella visualizzazione
	 * degli elementi.
	 * 
	 * @author Sivieri Alessandro
	 * @author Vitucci Nicola
	 * @version 12/mag/07
	 */
	private static final class ElementStruct
	{
		/**
		 * Numero progressivo della traccia (non corrisponde al numero
		 * in elenco nella tabella delle tracce, ma all'ordine cardinale
		 * delle tracce da codificare).
		 */
		public int number=0;
		/**
		 * Titolo della traccia.
		 */
		public String title=null;
		/**
		 * Operazione in corso sulla traccia.
		 */
		public EncodingOps op=null;

		/**
		 * Costruttore; setta gli attributi di classe con i
		 * valori specificati.
		 * 
		 * @param number
		 * @param title
		 * @param op
		 */
		public ElementStruct(int number, String title, EncodingOps op)
		{
			this.number = number;
			this.title = title;
			this.op = op;
		}
		
	}

	/**
	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
	 */
	@Override
	public void propertyChange(PropertyChangeEvent evt)
	{
		if(evt instanceof IndexedPropertyChangeEvent)
			setNewOp(((IndexedPropertyChangeEvent) evt).getIndex(), (EncodingOps) evt.getNewValue());
	}

}
